﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
using System.Diagnostics;
using System.Windows.Media;

namespace Rabbit.Controls
{
    public class HotKeyGenerateTextBox : TextBox
    {
        public HotKeyGenerateTextBox()
            : base()
        {
            this.Loaded += new RoutedEventHandler(HotKeyGenerateTextBox_Loaded);
            this.PreviewKeyDown += HotKeyGenerateTextBox_PreviewKeyDown;
            this.PreviewKeyUp += HotKeyGenerateTextBox_PreviewKeyUp;
            this.LostFocus += HotKeyGenerateTextBox_LostFocus;
            this.ContextMenu = null;
            this.ToolTip = "按下键设置";
        }
        void HotKeyGenerateTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!CheckValue())
            {
                ResetValue();
            }
        }

        void HotKeyGenerateTextBox_Loaded(object sender, RoutedEventArgs e)
        {
            if (Text =="")
            {
                SetCurrentValue(HotKeyGenerateTextBox.TextProperty, NoHotKeyTip);
            }
        }

        public string NoHotKeyTip
        {
            get { return (string)GetValue(NoHotKeyTipProperty); }
            set { SetValue(NoHotKeyTipProperty, value); }
        }

        // Using a DependencyProperty as the backing store for NoHotKeyTip.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty NoHotKeyTipProperty =
            DependencyProperty.Register("NoHotKeyTip", typeof(string),
            typeof(HotKeyGenerateTextBox),
            new UIPropertyMetadata("", new PropertyChangedCallback(
                (o, e) =>
                {
                    (o as HotKeyGenerateTextBox).SetCurrentValue(HotKeyGenerateTextBox.TextProperty, e.NewValue);
                })));

        public void SetHotKeyInvalid(string toolTip="不可设置重复的热键")
        {
            SetCurrentValue(TextBox.BorderBrushProperty, Brushes.Red);
            SetValue(TextBox.ToolTipProperty, toolTip);
        }

        public void ClearInvalidInformation()
        {
            ClearValue(TextBox.BorderBrushProperty);
            SetValue(TextBox.ToolTipProperty, "按下键设置");
        }

        public bool IsValidHotKey { 
            get
            {
                return CheckValue();
            }
        }

        public ModifierKeys ModifierKey
        {
            get
            {
                if (IsValidHotKey)
                {
                    string controlKey = this.Text.Substring(0,this.Text.LastIndexOf('+')).Replace("+",",").Replace("Ctrl","Control");
                    ModifierKeys mk;
                    if (Enum.TryParse<ModifierKeys>(controlKey, out mk))
                    {
                        return mk;
                    }
                }
                throw new InvalidOperationException("invalid hot key group");
            }
        }
        public uint KeyCode { 
            get{
               char key = this.Text.Substring(this.Text.LastIndexOf('+')+1)[0];
               return (uint)key;
            }
        }

        bool IsKeyDown = false;
        private void HotKeyGenerateTextBox_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            e.Handled = true;
            HotKeyGenerateTextBox temp = (sender as HotKeyGenerateTextBox);
            if (IsKeyDown == false)
            {
                temp.SetCurrentValue(HotKeyGenerateTextBox.TextProperty, NoHotKeyTip);
                IsKeyDown = true;
            }
            if (e.IsRepeat)
            {
                return;
            }
            Debug.Print(e.Key.ToString() + "\t" + e.SystemKey.ToString());

            if (e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.LWin || e.Key == Key.RWin)
            {
                temp.SetCurrentValue(HotKeyGenerateTextBox.TextProperty, NoHotKeyTip);
                e.Handled = true;
                return;
            }

            Key key = e.Key;
            if (e.Key == Key.System)
            {
                key = e.SystemKey;
            }

            if (key >= Key.A && key <= Key.Z)
            {
                if (Keyboard.Modifiers == ModifierKeys.None)
                {
                    temp.SetCurrentValue(TextBox.TextProperty, string.Format("{0}+{1}+{2}",
                        "Alt",
                        "Ctrl",
                        key));
                }
                else
                {
                    temp.Text =
                        string.Format("{0}+{1}",
                            Keyboard.Modifiers.ToString().Replace(",", "+").Replace("Control", "Ctrl"),
                            key);
                }
            }
            else if (key == Key.LeftAlt
                || key == Key.RightAlt
                || key == Key.RightCtrl
                || key == Key.LeftCtrl
                || key == Key.LeftShift
                || key == Key.RightShift
                )
            {
                string keyChar = key.ToString().Replace("Left", "").Replace("Right", "");

                if (temp.Text == NoHotKeyTip)
                {
                    temp.Text = keyChar + "+";
                }
                else
                {
                    temp.Text += keyChar + "+";
                }
            }
            temp.SelectionStart = temp.Text.Length;
        }

        private void HotKeyGenerateTextBox_PreviewKeyUp(object sender, KeyEventArgs e)
        {
            if (!CheckValue())
            {
                ResetValue();
            }
        }

        private void ResetValue()
        {
            this.Text = NoHotKeyTip;
        }

        private bool CheckValue()
        {
            IsKeyDown = false;
            if (this.Text.Length<5)
            {
                return false;
            }

            try
            {
                string lastChar = this.Text.Substring(this.Text.Length - 1);
                Key lastKey = (Key)Enum.Parse(typeof(Key), lastChar);

                if (lastKey < Key.A || lastKey > Key.Z)
                {
                    return false;
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
